package top.zlhy7.module.dept.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import top.zlhy7.base.constant.CacheConstants;
import top.zlhy7.exception.ServiceException;
import top.zlhy7.module.dept.entity.SysDept;
import top.zlhy7.module.dept.mapper.SysDeptMapper;
import top.zlhy7.module.dept.service.ISysDeptService;
import top.zlhy7.module.dept.vo.SysDeptTreeVo;
import top.zlhy7.module.dept.vo.SysDeptVo;
import top.zlhy7.utils.MapstructUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static top.zlhy7.base.constant.Constants.SQL_LIMIT_ONE;
import static top.zlhy7.base.constant.Constants.TOP_DEPT_ID;

/**
 * @author renyong
 * @date 2024/9/29 19:35
 * @description 部门实现类 服务
 */
@RequiredArgsConstructor
@Slf4j
@Service("sysDeptService")
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper,SysDept> implements ISysDeptService {
    /**
     * 根据父级部门id查询部门列表
     * @param parentId 父级部门id
     * @return
     * @author renyong on 2024/9/29 22:59
     */
    @Cacheable(value = CacheConstants.SYS_DEPT_PARENT_ID, key = "#parentId")
    @Override
    public List<SysDept> findAllByParentId(Long parentId) {
        if(parentId == null){
            return Collections.EMPTY_LIST;
        }
        LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery(SysDept.class)
                .eq(SysDept::getParentId,parentId)
                .orderByAsc(SysDept::getSort)
                .orderByDesc(SysDept::getCreateTime);
        return list(lqw);
    }
    /**
     * 校验数据
     * @param sysDeptVo 部门Vo
     * @return
     * @author renyong on 2024/9/29 23:01
     */
    public void checkData(SysDeptVo sysDeptVo){
        LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery(SysDept.class)
                .eq(SysDept::getParentId,sysDeptVo.getParentId())
                .last(SQL_LIMIT_ONE);
        // 父级部门!=顶级部门 && 父级部门不存在
        boolean flag = TOP_DEPT_ID.compareTo(sysDeptVo.getParentId())!=0 && count(lqw) == 0;
        if (flag){
            throw new ServiceException("父级部门不存在");
        }
        // 同父级下，部门名称不可重复
        lqw.clear();
        lqw.eq(SysDept::getParentId,sysDeptVo.getParentId())
            .eq(SysDept::getDeptName,sysDeptVo.getDeptName())
            .ne(sysDeptVo.getDeptId()!=null,SysDept::getDeptId,sysDeptVo.getDeptId());
        flag = count(lqw) > 0;
        if (flag){
            throw new ServiceException().format("部门名称【{}】记录已存在",sysDeptVo.getDeptName());
        }
    }
    /**
     * 新增
     * @param sysDeptVo 部门Vo
     * @return
     * @author renyong on 2024/9/29 21:43
     */
    @CacheEvict(value = CacheConstants.SYS_DEPT,allEntries = true)
    @Override
    public void insert(SysDeptVo sysDeptVo) {
        if(sysDeptVo == null){
            throw new ServiceException("参数错误");
        }
        // 校验数据
        checkData(sysDeptVo);
        SysDept sysDept = MapstructUtils.convert(sysDeptVo, SysDept.class);
        sysDept.insertBefore();
        save(sysDept);
    }
    /**
     * 修改
     * @param sysDeptVo 部门Vo
     * @return
     * @author renyong on 2024/9/29 21:43
     */
    @CacheEvict(value = CacheConstants.SYS_DEPT,allEntries = true)
    @Override
    public void update(SysDeptVo sysDeptVo) {
        if(sysDeptVo == null){
            throw new ServiceException("参数错误");
        }
        // 校验数据
        checkData(sysDeptVo);
        SysDept sysDept = MapstructUtils.convert(sysDeptVo, SysDept.class);
        sysDept.updateBefore();
        updateById(sysDept);
    }
    /**
     * 删除
     * @param id 主键
     * @return
     * @author renyong on 2024/9/29 21:59
     */
    @CacheEvict(value = CacheConstants.SYS_DEPT,allEntries = true)
    @Override
    public void delete(Long id) {
        if(id == null){
            throw new ServiceException("参数错误");
        }
        SysDept sysDept = getById(id);
        if (sysDept == null){
            throw new ServiceException("部门不存在");
        }
        LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery(SysDept.class)
                .eq(SysDept::getParentId,id);
        boolean flag = count(lqw) > 0;
        if (flag){
            throw new ServiceException("该部门下存在子部门，无法删除");
        }
        removeById(id);
    }
    /**
     * 全量返回所有部门-树形结构,数据量少时可以这么做，否则建议使用分步查询
     * @param
     * @return
     * @author renyong on 2024/9/29 23:36
     */
    @Cacheable(value = CacheConstants.SYS_DEPT, key = "'allTree'")
    @Override
    public List<SysDeptTreeVo> findTree() {
        LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery(SysDept.class)
                .orderByAsc(SysDept::getSort)
                .orderByDesc(SysDept::getCreateTime);
        List<SysDeptTreeVo> sysDeptList = list(lqw).stream()
                .map(sysDept -> MapstructUtils.convert(sysDept, SysDeptTreeVo.class))
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(sysDeptList)){
            return Collections.EMPTY_LIST;
        }
        Map<Long, List<SysDeptTreeVo>> sysDeptGroupMap = sysDeptList.stream()
                .collect(Collectors.groupingBy(SysDeptTreeVo::getParentId));
        for (SysDeptTreeVo sysDept : sysDeptList) {
            sysDept.setChildren(sysDeptGroupMap.get(sysDept.getDeptId()));
        }
        return sysDeptGroupMap.get(TOP_DEPT_ID);
    }
}
